package is.BlackWhiteSquares.formulas;

import java.util.ArrayList;
import java.util.List;

import es.deusto.ingenieria.is.search.algorithms.Node;
import es.deusto.ingenieria.is.search.algorithms.heuristic.EvaluationFunction;
import es.deusto.ingenieria.is.search.algorithms.heuristic.HeuristicSearchMethod;
import es.deusto.ingenieria.is.search.algorithms.log.SearchLog;
import es.deusto.ingenieria.is.search.formulation.Operator;
import es.deusto.ingenieria.is.search.formulation.Problem;
import es.deusto.ingenieria.is.search.formulation.State;
import es.deusto.ingenieria.is.search.xml.StateXMLReader;

public class HillClimbing extends HeuristicSearchMethod{

	public HillClimbing(EvaluationFunction function) {
		super(function);
		// TODO Auto-generated constructor stub
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

	@Override
	public Node search(Problem p, State st) {
		// TODO Auto-generated method stub
		State initialNode = p.gatherPercepts(st);
		
		State CurrentNode = initialNode;
		
		Node BestSuccessor = null;
		
		boolean local_best=false;
		
		Node firstNode = null;

		SearchLog searchLog = this.createSearchLog();
		
		Node finalState = null;
		
		while(!local_best){
			
			BestSuccessor=expand(firstNode, p).get(0);
			Node NCurrentNode = new Node(CurrentNode);
			
			//If currentnode better or equal to BestSuccessor
			if (NCurrentNode.getH()<=BestSuccessor.getH()) {
				
				local_best = true;
				finalState = NCurrentNode;
					
			} else {
				
				NCurrentNode = BestSuccessor;
				finalState = NCurrentNode;

			}
		}
		this.closeSearchLog(searchLog);
		
	
		return finalState;
	}
	
	public List<Node> expand(Node node, Problem problem) { // meter el gather perceps
		
		List<Node> successorNodes = new ArrayList<Node>();
		
		State currentState = null;
		
		State successorState = null;
		
		Node BestSuccesor = null;
		
		Node currentNode = null;
		
		
		if (node != null && problem != null) {
		
			currentState = node.getState();
						
			
			if (currentState != null && problem.isFullyObserved(currentState)!=false) {
				//if(((BlWhSquaresProblem)problem).isFinalState(currentState)!=false){
				
					for (Operator operator : problem.getOperators()) {
					
						successorState = operator.apply(currentState);
						currentNode = new Node(successorState);

						if (currentNode.getH() <= BestSuccesor.getH()) {

							BestSuccesor = currentNode;
						
							successorNodes.add(BestSuccesor);
						}
					}
				//}
			}else{
				
				currentNode = new Node(((BlWhSquaresProblem)problem).gatherPercepts(currentState));
				
				BestSuccesor = currentNode;
				
				successorNodes.add(BestSuccesor);
			}
		}
		
		return successorNodes;
	}

}
